import { watch } from "vue"
import {
    ExerciseType,
    Exercise,
    LearningProgress,
    ProgressType,
    NewWordExercise,
    ChineseChoiceEnglishExercise,
    ChinesePronounceEnglishExercise,
    ChineseSpellingEnglishExercise,
    EnglishChoiceChineseExercise,
    PronounceChoiceChineseExercise,
} from "../../model"
import { useConfigStore } from "../config"
import { useProgressStore, useWordStore } from ".."
import { toArray } from "../../utils"

// 观察一个未完成的习题，完成后进行处理u
export function watchExerciseFinish(exercise: Exercise) {
    if (exercise.result != undefined) return
    const stop = watch(
        () => exercise.resultCorrect,
        (v) => {
            if (v != undefined) {
                stop()
                handleExercise(exercise)
            }
        }
    )
}

function handleExercise(exercise: Exercise) {
    if (exercise.result == undefined) {
        return
    }
    switch (exercise.type) {
        case ExerciseType.NEW_WORD_EXERCISE:
            return handleNewWordExercise(exercise)
        case ExerciseType.ENGLISH_CHOICE_CHINESE_EXERCISE:
            return handleEnglishChooseChineseExercise(exercise)
        case ExerciseType.CHINESE_CHOICE_ENGLISH_EXERCISE:
            return handleChineseChooseEnglishExercise(exercise)
        case ExerciseType.PRONOUNCE_CHOICE_CHINESE_EXERCISE:
            return handlePronounceChooseChineseExercise(exercise)
        case ExerciseType.CHINESE_SPELLING_ENGLISH_EXERCISE:
            return handleChineseSpellingEnglishExercise(exercise)
        case ExerciseType.CHINESE_PRONOUNCE_ENGLISH_EXERCISE:
            return handleChinesePronounceEnglishExercise(exercise)
        default:
            ;((x: never) => x)(exercise)
    }
}

function handleProgress(
    progress: LearningProgress,
    baseExp: number,
    correct: boolean,
    timekeeping: number
) {
    const { config } = useConfigStore()
    const { progresses } = useProgressStore()
    progress.lastTestTime = Date.now()
    if (correct) {
        if (timekeeping < 5 * 1000) progress.proficiency *= 1.15
        else if (timekeeping < 10 * 1000) progress.proficiency *= 1.1
        else if (timekeeping < 15 * 1000) progress.proficiency *= 1.05

        if (progress.exp >= config.skilledRequiredExp) {
            progress.exp += Math.trunc(baseExp * progress.proficiency)
            config.forgettingSpeed /= 1.01
            progress.nextTestTime = Math.trunc(
                Date.now() +
                    (Math.ceil(progress.exp / config.skilledRequiredExp) *
                        config.skilledProgessBaseTestInterval) /
                        config.forgettingSpeed
            )
        } else {
            config.learningSpeed *= 1.01
            progress.exp += Math.trunc(
                baseExp * progress.proficiency * config.learningSpeed
            )
        }
    } else {
        if (progress.exp >= config.skilledRequiredExp) {
            if (progress.proficiency > 1) progress.proficiency = 1
            progress.exp = Math.trunc(config.skilledRequiredExp - baseExp * 3)
            if (progress.exp < 0) progress.exp = 0
            progresses
                .filter((p) => p.word == progress.word)
                .forEach((p) => (p.nextTestTime = undefined))
            config.forgettingSpeed *= 1.01
        } else {
            config.learningSpeed /= 1.01
            progress.proficiency *= 0.95
            progress.exp -= Math.trunc(
                baseExp / progress.proficiency / config.learningSpeed
            )
            if (progress.exp < 0) progress.exp = 0
        }
    }
}

function handleNewWordExercise(exercise: NewWordExercise) {
    const { getWord, setWordLearned } = useWordStore()
    const { addProgress } = useProgressStore()
    const word = getWord(exercise.word)
    setWordLearned(word)
    const wordProgresses: LearningProgress[] = []
    const baseDate = {
        word: word.word,
        proficiency: 1,
        exp: 0,
        lastTestTime: Date.now(),
    }
    wordProgresses.push({
        type: ProgressType.LISTEN,
        ...baseDate,
    })
    wordProgresses.push({
        type: ProgressType.SPEAK,
        ...baseDate,
    })
    wordProgresses.push({
        type: ProgressType.SPELL,
        ...baseDate,
    })
    toArray(word.meanings).forEach((m) => {
        wordProgresses.push({
            type: ProgressType.WORD_MEANING,
            meaning: m,
            ...baseDate,
        })
    })
    wordProgresses.forEach((p) =>
        handleProgress(
            p,
            5,
            exercise.result == exercise.correctOption,
            exercise.timekeeping as number
        )
    )
    wordProgresses.forEach(addProgress)
}

function handleEnglishChooseChineseExercise(
    exercise: EnglishChoiceChineseExercise
) {
    const { getWordMeaningProgress } = useProgressStore()
    const progress = getWordMeaningProgress(exercise.word, exercise.meaning)
    handleProgress(
        progress,
        5,
        exercise.resultCorrect as boolean,
        exercise.timekeeping as number
    )
}

function handleChineseChooseEnglishExercise(
    exercise: ChineseChoiceEnglishExercise
) {
    const { getWordMeaningProgress } = useProgressStore()
    const progress = getWordMeaningProgress(exercise.word, exercise.meaning)
    handleProgress(
        progress,
        5,
        exercise.resultCorrect as boolean,
        exercise.timekeeping as number
    )
}

function handlePronounceChooseChineseExercise(
    exercise: PronounceChoiceChineseExercise
) {
    const { getWordProgresses } = useProgressStore()
    const progress = getWordProgresses(exercise.word).listen
    handleProgress(
        progress,
        5,
        exercise.resultCorrect as boolean,
        exercise.timekeeping as number
    )
}

function handleChinesePronounceEnglishExercise(
    exercise: ChinesePronounceEnglishExercise
) {
    const { getWordProgresses } = useProgressStore()
    const progress = getWordProgresses(exercise.word).speak
    handleProgress(
        progress,
        5,
        exercise.resultCorrect as boolean,
        exercise.timekeeping as number
    )
}

function handleChineseSpellingEnglishExercise(
    exercise: ChineseSpellingEnglishExercise
) {
    const { getWordProgresses } = useProgressStore()
    const progress = getWordProgresses(exercise.word).spell
    handleProgress(
        progress,
        5,
        exercise.resultCorrect as boolean,
        exercise.timekeeping as number
    )
}
